package br.com.futebol.ia.impl.rprop.utils;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.StringTokenizer;

import org.apache.log4j.Logger;

import br.com.futebol.util.CloseUtils;

/**
 * Carrega a basse de um arquivo de texto formatado como um CSV.
 * 
 * @author Thyago Schleuss - tschleuss@gmail.com
 */
public final class DataLoader {

    private static final Logger LOG = Logger.getLogger(DataLoader.class);

    /**
     * Dados de input.
     */
    private List<double[]> input = null;

    /**
     * Dados de output.
     */
    private List<double[]> output = null;

    /**
     * Carrega a base de dados.
     * 
     * @param resource
     */
    public void loadDatabase(final InputStream stream) {
        List<String> headers = null;
        double[] inData = null;
        double[] outData = null;

        StringTokenizer tokenizer = null;
        InputStreamReader reader = null;
        Scanner sc = null;

        int line = 0;
        int idxIn = 0;
        int idxOut = 0;
        int countInputs = 0;
        int countOutputs = 0;
        boolean hasTokens = false;

        try {

            reader = new InputStreamReader(stream);
            sc = new Scanner(reader);

            while (sc.hasNext()) {
                final String strLine = sc.nextLine();
                tokenizer = new StringTokenizer(strLine, ";");

                while (tokenizer.hasMoreTokens()) {
                    hasTokens = true;

                    if (line == 0) {
                        headers = new ArrayList<String>();
                        input = new ArrayList<double[]>();
                        output = new ArrayList<double[]>();
                        line++;
                    } else if (line == 1) {
                        final String token = tokenizer.nextToken();
                        if (token.startsWith("RES_")) {
                            countOutputs++;
                        } else {
                            countInputs++;
                        }
                        headers.add(token);
                    } else if (line >= 2) {

                        if (inData == null || outData == null) {
                            inData = new double[countInputs];
                            outData = new double[countOutputs];
                        }

                        final String token = tokenizer.nextToken();
                        if (headers.get(idxIn + idxOut).startsWith("RES_")) {
                            outData[idxOut] = Double.valueOf(token);
                            idxOut++;
                        } else {
                            inData[idxIn] = Double.valueOf(token);
                            idxIn++;
                        }
                    }
                }

                if (line >= 2 && hasTokens) {
                    input.add(inData.clone());
                    output.add(outData.clone());
                    inData = new double[countInputs];
                    outData = new double[countOutputs];
                }

                hasTokens = false;
                idxIn = 0;
                idxOut = 0;
                line++;
            }

        } catch (Exception e) {
            LOG.error("Erro ao carregar base de inteligencia", e);
        } finally {
            if (sc != null) {
                sc.close();
            }
            CloseUtils.close(reader);
        }
    }

    /**
     * Converte a lista para array e retorna.
     * 
     * @return
     */
    public double[][] getInput() {
        double[][] d = new double[input.size()][];
        for (int i = 0; i < input.size(); i++) {
            d[i] = input.get(i);
        }
        return d;
    }

    /**
     * Converte a lista para array e retorna.
     * 
     * @return
     */
    public double[][] getOutput() {
        double[][] d = new double[output.size()][];
        for (int i = 0; i < output.size(); i++) {
            d[i] = output.get(i);
        }
        return d;
    }
}
